package com.acheli.rideable.functionLathes.component;

import com.acheli.ACHeli;
import com.acheli.registry.config.CustomDataBus;
import com.acheli.registry.resource.DynamicResourcePack;
import com.acheli.rideable.entites.RideableEntity;
import com.acheli.rideable.functionLathes.ComponentFL;
import com.acheli.rideable.functionLathes.component.compile.JSUtils;
import com.acheli.utils.math.vec.Translate;
import com.google.gson.Gson;
import net.minecraft.resources.ResourceLocation;
import org.mozilla.javascript.*;

import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Objects;

import static com.acheli.ACHeli.MODID;


public class DefaultComponentFactoryRegistry {
    public static void register() {
        ACHeli.GsonComponentFLRegisterMap.put("seat", SeatFL.class);
        ACHeli.GsonComponentFLRegisterMap.put("shell", ShellHolderFL.class);
//        ACHeli.GsonComponentFactoryRegisterMap.put("engine", EngineFL.class);
//        ACHeli.GsonComponentFactoryRegisterMap.put("propeller", PropellerBase.class);
//        ACHeli.GsonComponentFactoryRegisterMap.put("stabilizer", StabilizerBase.class);

        showDocument();
    }

    public static DefaultComponentProvider registerForGsonDefaultComponentProvider (String PACKNAME, String componentName, String json) {
        System.out.println("defaultComponentProvider");
        Context JS_RUNNER = Context.enter();// 初始化 Rhino 上下文
        Scriptable JS_SCOPE = JS_RUNNER.initStandardObjects();
        NativeObject result = null;
        try {
            // 在 JS 中调用 Java 方法
            String jsCode = "JSON.parse('%s');".formatted(json);
            result = (NativeObject) JS_RUNNER.evaluateString(JS_SCOPE, jsCode, "defaultComponentProvider", 1, null);
            if ( ! Objects.equals(Context.toString(result), "undefined")) {
                System.out.println(result.getClass());
            }

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }  finally {
            Context.exit();
        }
        NativeObject finalResult = result;

        if (Objects.equals(componentName, "seat")) {
            SeatFL.Data seatData = new Gson().fromJson(json, SeatFL.Data.class);
            return new DefaultComponentProvider() {
                @Override
                public ComponentFL get(RideableEntity rideable) {
                    SeatFL seatFL = new SeatFL(
                            seatData.ID, rideable, seatData.canControl, seatData.maxRotateAngle,
                            ComponentFL.Orientation.valueOf(seatData.orientation),
                            Translate.convert(seatData.relativePosition),
                            Translate.convert(seatData.relativeBoxLength));
                    seatFL.setJS(finalResult);
                    return seatFL;
                }

                @Override
                public String getID() {
                    return seatData.ID;
                }
            };
        }
        if (Objects.equals(componentName, "shell")) {
            ShellHolderFL.Data shellData = new Gson().fromJson(json, ShellHolderFL.Data.class);
            return new DefaultComponentProvider() {
                @Override
                public ComponentFL get(RideableEntity rideable) {
                    ShellHolderFL shell = new ShellHolderFL(
                            shellData.ID, rideable,
                            Translate.convert(shellData.relativePosition),
                            Translate.convert(shellData.relativeBoxLength));
                    shell.setJS(finalResult);
                    return shell;
                }

                @Override
                public String getID() {
                    return shellData.ID;
                }
            };
        }

        return null;
    }

    private static void showDocument() {
        ACHeli.GsonComponentFLRegisterMap.forEach((name, clazz) -> {
            ACHeli.LOGGER.info("Enabled Component: " + name);

            try {
                // 2. 获取所有声明的构造函数
                Constructor<?>[] constructors = clazz.getDeclaredConstructors();
                int count = 1;
                for (Constructor<?> constructor : constructors) {
                    // 3. 获取参数列表
                    Parameter[] parameters = constructor.getParameters();
                    if (parameters.length == 0) {
                        ACHeli.LOGGER.warn(name + " has no parameters.");
                        continue;
                    }

                    StringBuilder params = new StringBuilder();
                    // 4. 遍历并打印参数信息
                    for (Parameter param : parameters) {
                        String paramType = param.getType().getSimpleName();
                        String paramName = param.getName();
                        params.append("  - paramType: ").append(paramType)
                                .append(", paramName: ").append(paramName);
                        params.append("\n");
                    }
                    ACHeli.LOGGER.info("\nThe No.%s constructor of %s : \n%s ".formatted(count, name, params));
                }
            } catch (Exception e) {
                ACHeli.LOGGER.info("Component %s Parameter print error: %s".formatted(name, e));
            }
        });
    }
}
